﻿using System.Collections.Generic;
using UnityEngine;


namespace ZGameFramework.UI
{
    internal sealed partial class UIManager : GameFrameworkModule, IUIManager
    {
        private IUIFormInfoManager m_UIFormInfoManager;
        private IUIResourceManager m_UIResourceManager;

        private GameObject m_UIRoot;
        private GameObject m_ScreenMask;
        private Dictionary<string, UIForm> m_DictUIForm;
        private List<UIForm> m_CacheOpenUIForm;
        private List<UIForm> m_CacheCloseUIForm;
        private Dictionary<string, float> m_FadeIningUIForm;
        private Dictionary<string, float> m_FadeOutingUIForm;

        private float m_LockScreenTime = -1;

        /// <summary>
        /// 构造函数
        /// </summary>
        public UIManager()
        {
            m_UIRoot = GameObject.Find("UIRoot");
            if (null == m_UIRoot)
            {
                m_UIRoot = Object.Instantiate(Resources.Load("UI/Perfab/UIRoot")) as GameObject;
                m_UIRoot.name = "UIRoot";
                Object.DontDestroyOnLoad(m_UIRoot);

                m_ScreenMask = m_UIRoot.transform.Find("Canvas/Canvas_4/UIScreenMask").gameObject;
            }

            m_DictUIForm = new Dictionary<string, UIForm>();
            m_CacheOpenUIForm = new List<UIForm>();
            m_CacheCloseUIForm = new List<UIForm>();
            m_FadeIningUIForm = new Dictionary<string, float>();
            m_FadeOutingUIForm = new Dictionary<string, float>();
        }


        /// <summary>
        /// 获取游戏框架模块优先级。
        /// </summary>
        /// <remarks>优先级较高的模块会优先轮询，并且关闭操作会后进行。</remarks>
        internal override int Priority
        {
            get
            {
                return 0;
            }
        }

        /// <summary>
        /// 游戏框架模块轮询。
        /// </summary>
        /// <param name="elapseSeconds">逻辑流逝时间，以秒为单位。</param>
        /// <param name="realElapseSeconds">真实流逝时间，以秒为单位。</param>
        internal override void Update(float elapseSeconds, float realElapseSeconds)
        {
            if (!UpdateLockScreenMask(elapseSeconds, realElapseSeconds))
            {
                if (m_CacheCloseUIForm.Count > 0)
                {
                    To_ClosePanel(m_CacheCloseUIForm[0]);
                    m_CacheCloseUIForm.RemoveAt(0);
                }
                else if (m_CacheOpenUIForm.Count > 0)
                {
                    To_OpenPanel(m_CacheOpenUIForm[0]);
                    m_CacheOpenUIForm.RemoveAt(0);
                }
            }
            UdpateFadeing(elapseSeconds, realElapseSeconds);
        }

        /// <summary>
        /// 关闭并清理游戏框架模块。
        /// </summary>
        internal override void Shutdown()
        {

        }


        /// <summary>
        /// 设置窗口管理信息
        /// </summary>
        /// <param name="uiFormInfoManager"></param>
        public void SetUIFormInfoManager(IUIFormInfoManager uiFormInfoManager)
        {
            m_UIFormInfoManager = uiFormInfoManager;
        }

        /// <summary>
        /// 设置UIResourceManager
        /// </summary>
        /// <param name="uIResourceManager"></param>
        public void SetUIResourceManager(IUIResourceManager uiResourceManager)
        {
            if (null == uiResourceManager)
            {
                Debug.LogError("uiResourceManager is null!!!");
                return;
            }


            m_UIResourceManager = uiResourceManager;
        }


        /// <summary>
        /// 打开界面
        /// </summary>
        public void OpenPanel(string panelName, GameFrameworkParam param = null)
        {
            if (m_DictUIForm.ContainsKey(panelName))
            {
                return;
            }

            UIForm uiForm = ReferencePool.Acquire<UIForm>();
            uiForm.SetManager(this);
            uiForm.SetFormInfo(m_UIFormInfoManager.GetUIFormInfo(panelName));
            uiForm.SetParam(param);
            if (!UpdateLockScreenMask(0, 0))
            {
                // 直接打开
                To_OpenPanel(uiForm);
            }
            else
            {
                // 缓存
                m_CacheOpenUIForm.Add( uiForm );
            }

            m_DictUIForm.Add(panelName, uiForm );
        }

        /// <summary>
        /// 关闭界面
        /// </summary>
        public void ClosePanel(string panelName)
        {
            if (!m_DictUIForm.ContainsKey(panelName))
            {
                return;
            }

            UIForm uiForm = m_DictUIForm[panelName];
            if (!UpdateLockScreenMask(0, 0))
            {
                // 直接关闭
                To_ClosePanel(uiForm);
            }
            else
            {
                // 缓存
                m_CacheCloseUIForm.Add( uiForm );
            }
           
        }

        /// <summary>
        /// 去 打开界面
        /// </summary>
        /// <param name="uiForm"></param>
        private void To_OpenPanel(UIForm uiForm)
        {
            uiForm.LoadBehavior(Do_OpenPanel);
        }

        /// <summary>
        /// 去关闭界面
        /// </summary>
        /// <param name="uiForm"></param>
        private void To_ClosePanel(UIForm uiForm)
        {
            float delay = uiForm.FaderOut();
            SetLockScreenTime(delay);
            m_FadeOutingUIForm.Add( uiForm.FormInfo.Name, delay );
        }

        /// <summary>
        /// 执行 打开界面 因为异步
        /// </summary>
        /// <param name="uiForm"></param>
        private void Do_OpenPanel(UIForm uiForm)
        {
            Transform tCanvas = m_UIRoot.transform.Find(string.Format("Canvas/Canvas_{0}", uiForm.FormInfo.Canvas));
            uiForm.Behaivour.m_GameObject.transform.SetParent(tCanvas);
            uiForm.Behaivour.m_GameObject.transform.SetNormalize();
            RectTransform rectTransform = uiForm.Behaivour.m_GameObject.GetComponent<RectTransform>();
            rectTransform.anchoredPosition = Vector2.zero;
            rectTransform.sizeDelta = Vector2.zero;
            float delay = uiForm.FadeIn();
            SetLockScreenTime(delay);
            m_FadeIningUIForm.Add( uiForm.FormInfo.Name, delay );
        }

        /// <summary>
        /// 执行 关闭界面 和打开界面匹配
        /// </summary>
        /// <param name="uiForm"></param>
        private void Do_ClosePanel(UIForm uiForm)
        {
            m_DictUIForm.Remove(uiForm.FormInfo.Name);
            ReferencePool.Release(uiForm);
        }
      

        /// <summary>
        /// 更新Update
        /// </summary>
        /// <param name="elapseSeconds"></param>
        /// <param name="realElapseSeconds"></param>
        private bool UpdateLockScreenMask(float elapseSeconds, float realElapseSeconds)
        {
            bool results = false;
            if (m_LockScreenTime > 0)
            {
                results = true;
                m_LockScreenTime -= elapseSeconds;
                if (m_LockScreenTime <= 0)
                {
                    SetActiveScreenMask( false );
                    results = false;
                    m_LockScreenTime = -1;
                }
            }
            return results;
        }

        /// <summary>
        /// 设置锁定时间
        /// </summary>
        /// <param name="lockScreenTime"></param>
        private void SetLockScreenTime(float lockScreenTime)
        {
            if (lockScreenTime > 0)
            {
                m_LockScreenTime = lockScreenTime;
                SetActiveScreenMask( true );
            }
        }

        /// <summary>
        /// 设置屏幕 遮罩
        /// </summary>
        /// <param name="isActive"></param>
        private void SetActiveScreenMask(bool isActive)
        {
            if (null != m_ScreenMask && m_ScreenMask.activeSelf != isActive ) 
            {
                m_ScreenMask.SetActive( isActive );
            }
        }

        /// <summary>
        /// 更新Fadeing
        /// </summary>
        private void UdpateFadeing(float elapseSeconds, float realElapseSeconds)
        {
            if (m_FadeIningUIForm.Count > 0)
            {
                List<string> names = new List<string>(m_FadeIningUIForm.Keys);
                foreach (var name in names)
                {
                    m_FadeIningUIForm[name] -= elapseSeconds;
                    if (m_FadeIningUIForm[name] <= 0)
                    {
                        m_FadeIningUIForm.Remove(name);
                        UIForm uiForm = null;
                        if (m_DictUIForm.TryGetValue(name, out uiForm))
                        {
                            uiForm.FadeInAfter();
                        }
                    }
                }
            }

            if (m_FadeOutingUIForm.Count > 0)
            {
                List<string> names = new List<string>(m_FadeOutingUIForm.Keys);
                foreach (var name in names)
                {
                    m_FadeOutingUIForm[name] -= elapseSeconds;
                    if (m_FadeOutingUIForm[name] <= 0)
                    {
                        m_FadeOutingUIForm.Remove(name);

                        UIForm uiForm = null;
                        if (m_DictUIForm.TryGetValue(name, out uiForm))
                        {
                            uiForm.FadeOutAfter();
                            Do_ClosePanel( uiForm );
                        }
                    }
                }

            }
        }

    }

}